#include <QCloseEvent>
#include <QDebug>
#include <QHeaderView>
#include <QMenu>
#include <QMessageBox>
#include <QSound>
#include <QTimer>

#include "Configuration.h"
#include "Server.h"
#include "ServerManager.h"
#include "MainWindow.h"
#include "ManageDialog.h"
#include "ui_MainWindow.h"

MainWindow::MainWindow( Configuration *configuration,
                        ServerManager *serverManager,
                        QWidget *parent ) :
    QMainWindow( parent ),
    ui( new Ui::MainWindow ),
    mConfiguration( configuration ),
    mLastAlarmId( -1 ),
    mServerManager( serverManager ),
    mSystemTrayIcon( new QSystemTrayIcon(this) ),
    mResetTimer( new QTimer(this) )
{
    ui->setupUi( this );
    setWindowIcon( QIcon(":/icons/application.png") );

    // Model.
    QAbstractItemModel *model = serverManager->model();
    ui->tableView->setModel( model );
    ui->tableView->resizeColumnsToContents();

    // Headers.
    QHeaderView *horizontalHeader = ui->tableView->horizontalHeader();
    horizontalHeader->setResizeMode( QHeaderView::ResizeToContents );
    QHeaderView *verticalHeader = ui->tableView->verticalHeader();
    verticalHeader->hide();

    // Reset timer.
    mResetTimer->setInterval( 10 * 1000 ); // 10 seconds.
    mResetTimer->setSingleShot( true );

    // Tray icon.
    mSystemTrayIcon->setIcon( QIcon(":icons/application.png") );
    mSystemTrayIcon->setToolTip( qApp->applicationName() );
    QMenu *trayMenu = new QMenu( this );
    mSystemTrayIcon->setContextMenu( trayMenu );
    trayMenu->addAction( ui->actionManage );
    trayMenu->addAction( ui->actionHelp );
    trayMenu->addAction( ui->actionAbout );
    trayMenu->addAction( ui->actionAboutQt );
    trayMenu->addAction( ui->actionQuit );

    // Connections.
    connect( mServerManager, SIGNAL(serverCritical(int)),
             this, SLOT(alarm(int)) );
    connect( mSystemTrayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
             this, SLOT(trayEvent(QSystemTrayIcon::ActivationReason)) );
    connect( mResetTimer, SIGNAL(timeout()),
             this, SLOT(resetLastAlarmId()) );
    connect( ui->actionAbout, SIGNAL(triggered()),
             this, SLOT(about()) );
    connect( ui->actionAboutQt, SIGNAL(triggered()),
             qApp, SLOT(aboutQt()) );
    connect( ui->actionHelp, SIGNAL(triggered()),
             this, SLOT(help()) );
    connect( ui->actionManage, SIGNAL(triggered()),
             this, SLOT(manage()) );
    connect( ui->actionRefresh, SIGNAL(triggered()),
             mServerManager, SLOT(start()) );
    connect( ui->actionQuit, SIGNAL(triggered()),
             qApp, SLOT(quit()) );

    // Start minimized.
    setWindowState( Qt::WindowMinimized );
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::about()
{
    QString text = tr(
    "<p>This tool is able to monitor a server or webspace. It can "
    "simply ping and with support of the server it can also "
    "measure resource usage (xml based). For more informations visit "
    "the project at <a href=\"http://code.google.com/p/still-there/\">"
    "Google Project Hosting</a>.</p>"

    "<h1>Icons - Must Have</h1>"
    "<p>These icons are distributed under a Creative Commons Attribution-"
    "No Derivative Works 3.0 Unported License. </p>"

    "<p>You are free: to Share ? to copy, distribute and transmit the work "
    "under the following conditions: </p>"

    "<p>Attribution. You must attribute the work in the manner specified by the "
    "author or licensor (but not in any way that suggests that they endorse "
    "you or your use of the work). </p>"

    "<p>No Derivative Works. You may not alter, transform, or build upon this work. <p>"

    "<p>For any reuse or distribution, you must make clear to others the license "
    "terms of this work. The best way to do this is with a link to the "
    "<a href=\"http://creativecommons.org/licenses/by-nd/3.0/\">"
    "http://creativecommons.org/licenses/by-nd/3.0/</a> web page. </p>"

    "<p>Any of the above conditions can be waived if you get permission from the "
    "copyright holder. </p>"

    "<p>Nothing in this license impairs or restricts the author's moral rights. </p>"

    "<p>It means the icons are free for personal use and also free for commercial "
    "use, but we require linking to our web site. If you don't want to place a "
    "link, purchase them for $199 per set. <p>"

    "<p><a href=\"http://www.visualpharm.com/must_have_icon_set/\">"
    "http://www.visualpharm.com/must_have_icon_set/</a></p>"
    );

    QMessageBox::about(
        this,
        tr("About"),
        text
    );
}

void MainWindow::alarm( int id )
{
    if ( mLastAlarmId == id )
    {
        return;
    }
    mLastAlarmId = id;
    mResetTimer->stop(); // Stop possible running timer.
    mResetTimer->start();

    if ( mConfiguration->showPopup() )
    {
        if ( mSystemTrayIcon->supportsMessages() )
        {
            Server *server = mServerManager->servers()->at( id );

            mSystemTrayIcon->showMessage( tr("Critical value"),
                                          tr("Server \"%1\" has a critical value.")
                                          .arg( server->name() ),
                                          QSystemTrayIcon::Critical );
        }
    }

    if ( mConfiguration->playSound() )
    {
        if ( QSound::isAvailable() )
        {
            QSound::play( mConfiguration->alarmSoundPath() );
        }
        else
        {
            qDebug() << "MainWindow: No sound interface found.";
        }
    }
}

void MainWindow::changeEvent( QEvent *e )
{

    QMainWindow::changeEvent(e);

    if ( e->type() == QEvent::WindowStateChange &&
         windowState() == Qt::WindowMinimized )
    {
        e->accept();

        // Show tray icon.
        mSystemTrayIcon->show();

        // Prevent app from quiting when closing a window in tray mode.
        qApp->setQuitOnLastWindowClosed( false );
        QTimer::singleShot( 0, this, SLOT(hide()) ); // IMPORTANT
    }
}

void MainWindow::closeEvent( QCloseEvent *e )
 {
    e->accept();

    // Reactivate normal quit behaviour.
    qApp->setQuitOnLastWindowClosed( true );
}

void MainWindow::help()
{
    QString text = tr(
    "To add a server or a website open the \"manage\" dialog. "
    "The first tab contains a couple of general settings. The "
    "second tab allows you to add servers and websites. You must "
    "enter the url with the scheme otherwise it won't be accepted. "
    "To use the xml based API for reading server statistics you must "
    "first install a script or something similar which will read the "
    "values (currently only cpu load). Then you must enter the url to "
    "the xml file in the \"manage\" dialog."
    );

    QMessageBox msgBox;
    msgBox.setWindowTitle( tr("Help") );
    msgBox.setText( text );
    msgBox.exec();
}

void MainWindow::manage()
{
    ManageDialog dialog( mConfiguration, mServerManager->servers() );
    connect( &dialog, SIGNAL(createServer(QString,QUrl)),
             mServerManager, SLOT(createServer(QString,QUrl)) );
    connect( &dialog, SIGNAL(deleteServer(int)),
             mServerManager, SLOT(deleteServer(int)) );
    connect( &dialog, SIGNAL(editServer(int,ServerManager::ServerSettings)),
             mServerManager, SLOT(editServer(int,ServerManager::ServerSettings)) );
    dialog.exec();

    mConfiguration->save();
}

void MainWindow::resetLastAlarmId()
{
    mLastAlarmId = -1;
}

void MainWindow::trayEvent( const QSystemTrayIcon::ActivationReason &reason )
{
    if ( reason == QSystemTrayIcon::DoubleClick )
    {
        // Restore window correct
        show();
        if( isMinimized() )
        {
            if( isMaximized() )
            {
                showMaximized();
            }
            else
            {
                showNormal();
            }
        }
        raise();
        activateWindow();

        // Hide tray icon.
        mSystemTrayIcon->hide();

        // Reactivate normal quit behaviour.
        qApp->setQuitOnLastWindowClosed( true );
    }
}
